package top.syfy.video;

import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 视频文件处理工具类
 */

@SuppressWarnings({"all"})
public class App {

    private static final Logger logger = LoggerFactory.getLogger(App.class);

    // 需要获取的帧数（为了防止获取到的是黑色图片，可以将帧数设置得大些）
    private static final int VIDEO_FRAMES_OFFSET = 10;
    // 支持的视频格式
    private static final String[] FORMATS = {".mov", ".mp4", ".m4a", ".3gp", ".3g2", ".mj2"};
    // 图片类型（一般为jpg、png）
    private static final String IMAGE_MAT = "png";

    public static void main(String[] args) {
        File fileDir = new File("/Users/syfy/Videos/v");
        if (!fileDir.exists()) {
            logger.error("指定的目录不存在：【{}】", fileDir.getAbsolutePath());
            return;
        }

        File[][] videoAndType = new File[FORMATS.length][];

        // 过滤，获取支持的文件
        for (int i = 0; i < FORMATS.length; i++) {
            int finalI = i;
            File[] tmp = fileDir.listFiles(v -> v.getName().endsWith(FORMATS[finalI]));
            Arrays.sort(Objects.requireNonNull(tmp));
            videoAndType[i] = tmp;
        }

        // 统计存在符合条件的视频文件数量
        int itemCount = 0;
        for (File[] videos : videoAndType) {
            itemCount += videos.length;
        }

        // 判断存在符合条件的视频文件数量
        if (itemCount < 1) {
            logger.error("指定的目录【{}】下不存在符合条件的视频文件：【{}】", fileDir.getAbsolutePath(), Arrays.toString(FORMATS).replaceAll("\\[|\\]", ""));
            return;
        }
        
        // 遍历
        for (File[] videos : videoAndType) {
            for (int j = 0; j < Objects.requireNonNull(videos).length; j++) {
                Map<String, Object> screenshot = getScreenshot(videos[j].getAbsolutePath());
                System.out.println(screenshot.toString());
            }
        }

    }

    /**
     * 获取视频的截图并保存为同名的指定格式文件到指定文件
     *
     * @param filePath 视频文件的路径
     * @return 视频基本信息Map集合
     */
    public static Map<String, Object> getScreenshot(String filePath) {
        logger.info("视频文件【{}】截图开始", filePath);

        Map<String, Object> result = new HashMap<>();
        String separator = ".";
        FFmpegFrameGrabber grabber;
        try {
            grabber = FFmpegFrameGrabber.createDefault(filePath);
            // 图片存放位置（视频路径）
            String targetFilePath = filePath.substring(0, filePath.lastIndexOf(File.separator));
            // 视频文件名（含扩展名）
            String fileName = filePath.substring(filePath.lastIndexOf(File.separator) + 1);
            // 图片名称（不含扩展名）
            String targetFileName = fileName.substring(0, fileName.lastIndexOf(separator));

            grabber.start();
            // 获取视频的总帧数
            int videoFrames = grabber.getLengthInFrames();
            Frame frame = null;
            int i = 0;
            while (i < videoFrames) {
                // 过滤前指定帧数（每循环一次取一帧）
                frame = grabber.grabFrame();
                if ((i > VIDEO_FRAMES_OFFSET) && (frame.image != null)) {
                    break;
                }
                i++;
            }

            Java2DFrameConverter converter = new Java2DFrameConverter();
            // 绘制图片
            BufferedImage bi = converter.getBufferedImage(frame);
            // 图片的完整路径
            String imagePath = targetFilePath + File.separator + targetFileName + separator + IMAGE_MAT;

            // 创建文件
            File output = new File(imagePath);
            ImageIO.write(Objects.requireNonNull(bi), IMAGE_MAT, output);

            /*
                拼接Map信息
             */
            // 视频帧数
            result.put("videoLength", videoFrames);
            // 视频的宽
            result.put("videoWide", bi.getWidth());
            // 视频的高
            result.put("videoHigh", bi.getHeight());
            // 视频时长（秒）
            result.put("duration", grabber.getLengthInTime() / (1000 * 1000));
            // 视频格式
            result.put("format", grabber.getFormat());
            // 图片路径
            result.put("thumbnailPath", output.getPath());

            grabber.stop();
            logger.info("视频文件【{}】截图结束，缩略图地址为【{}】", filePath, imagePath);
        } catch (IOException e) {
            logger.error("视频信息帧数处理发生异常【{}】", e.getMessage());
            e.printStackTrace();
        }
        return result;
    }

}

